package com.example.service;

import com.example.model.SystemConfig;
import com.example.repository.SystemConfigRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

@Service
@Transactional
public class SystemConfigServiceImpl implements SystemConfigService {
    
    @Autowired
    private SystemConfigRepository systemConfigRepository;
    
    @Override
    public SystemConfig createConfig(SystemConfig config) {
        if (existsByKey(config.getConfigKey())) {
            throw new RuntimeException("配置键已存在: " + config.getConfigKey());
        }
        return systemConfigRepository.save(config);
    }
    
    @Override
    public SystemConfig updateConfig(SystemConfig config) {
        if (!systemConfigRepository.existsById(config.getId())) {
            throw new RuntimeException("配置不存在");
        }
        
        // 检查配置键是否与其他配置冲突
        Optional<SystemConfig> existingByKey = systemConfigRepository.findByConfigKey(config.getConfigKey());
        if (existingByKey.isPresent() && !existingByKey.get().getId().equals(config.getId())) {
            throw new RuntimeException("配置键已存在: " + config.getConfigKey());
        }
        
        return systemConfigRepository.save(config);
    }
    
    @Override
    public void deleteConfig(Long id) {
        systemConfigRepository.deleteById(id);
    }
    
    @Override
    public Optional<SystemConfig> findById(Long id) {
        return systemConfigRepository.findById(id);
    }
    
    @Override
    public Optional<SystemConfig> findByKey(String key) {
        return systemConfigRepository.findByConfigKey(key);
    }
    
    @Override
    public List<SystemConfig> findAllVisibleConfigs() {
        return systemConfigRepository.findByIsVisibleTrueOrderByCategory();
    }
    
    @Override
    public Page<SystemConfig> findAllVisibleConfigs(Pageable pageable) {
        return systemConfigRepository.findByIsVisibleTrue(pageable);
    }
    
    @Override
    public List<SystemConfig> findByCategory(String category) {
        return systemConfigRepository.findByCategoryOrderByConfigKey(category);
    }
    
    @Override
    public List<SystemConfig> findEditableConfigs() {
        return systemConfigRepository.findByIsEditableTrueOrderByCategory();
    }
    
    @Override
    public List<SystemConfig> searchConfigsByKey(String key) {
        return systemConfigRepository.findByConfigKeyContainingAndIsVisibleTrue(key);
    }
    
    @Override
    public String getConfigValue(String key) {
        return getConfigValue(key, null);
    }
    
    @Override
    public String getConfigValue(String key, String defaultValue) {
        Optional<SystemConfig> configOpt = systemConfigRepository.findByConfigKey(key);
        return configOpt.map(SystemConfig::getConfigValue).orElse(defaultValue);
    }
    
    @Override
    public Integer getIntConfigValue(String key) {
        return getIntConfigValue(key, null);
    }
    
    @Override
    public Integer getIntConfigValue(String key, Integer defaultValue) {
        Optional<SystemConfig> configOpt = systemConfigRepository.findByConfigKey(key);
        if (configOpt.isPresent()) {
            return configOpt.get().getIntegerValue();
        }
        return defaultValue;
    }
    
    @Override
    public Double getDoubleConfigValue(String key) {
        return getDoubleConfigValue(key, null);
    }
    
    @Override
    public Double getDoubleConfigValue(String key, Double defaultValue) {
        Optional<SystemConfig> configOpt = systemConfigRepository.findByConfigKey(key);
        if (configOpt.isPresent()) {
            return configOpt.get().getDoubleValue();
        }
        return defaultValue;
    }
    
    @Override
    public Boolean getBooleanConfigValue(String key) {
        return getBooleanConfigValue(key, null);
    }
    
    @Override
    public Boolean getBooleanConfigValue(String key, Boolean defaultValue) {
        Optional<SystemConfig> configOpt = systemConfigRepository.findByConfigKey(key);
        if (configOpt.isPresent()) {
            return configOpt.get().getBooleanValue();
        }
        return defaultValue;
    }
    
    @Override
    public void updateConfigs(Map<String, String> configs) {
        for (Map.Entry<String, String> entry : configs.entrySet()) {
            Optional<SystemConfig> configOpt = systemConfigRepository.findByConfigKey(entry.getKey());
            if (configOpt.isPresent()) {
                SystemConfig config = configOpt.get();
                if (config.getIsEditable()) {
                    config.setConfigValue(entry.getValue());
                    systemConfigRepository.save(config);
                }
            }
        }
    }
    
    @Override
    public Map<String, String> getConfigsByCategory(String category) {
        List<SystemConfig> configs = systemConfigRepository.findByCategoryOrderByConfigKey(category);
        return configs.stream()
                .collect(Collectors.toMap(
                    SystemConfig::getConfigKey,
                    SystemConfig::getConfigValue
                ));
    }
    
    @Override
    public Map<String, String> getAllConfigs() {
        List<SystemConfig> configs = systemConfigRepository.findByIsVisibleTrueOrderByCategory();
        return configs.stream()
                .collect(Collectors.toMap(
                    SystemConfig::getConfigKey,
                    SystemConfig::getConfigValue
                ));
    }
    
    @Override
    public SystemConfig setConfigVisible(Long id, Boolean visible) {
        Optional<SystemConfig> configOpt = systemConfigRepository.findById(id);
        if (configOpt.isPresent()) {
            SystemConfig config = configOpt.get();
            config.setIsVisible(visible);
            return systemConfigRepository.save(config);
        }
        throw new RuntimeException("配置不存在");
    }
    
    @Override
    public SystemConfig setConfigEditable(Long id, Boolean editable) {
        Optional<SystemConfig> configOpt = systemConfigRepository.findById(id);
        if (configOpt.isPresent()) {
            SystemConfig config = configOpt.get();
            config.setIsEditable(editable);
            return systemConfigRepository.save(config);
        }
        throw new RuntimeException("配置不存在");
    }
    
    @Override
    public void initializeDefaultConfigs() {
        // 系统基础配置
        createDefaultConfigIfNotExists("system.name", "洗护管理系统", "系统名称", "SYSTEM", SystemConfig.ConfigType.STRING);
        createDefaultConfigIfNotExists("system.version", "1.0.0", "系统版本", "SYSTEM", SystemConfig.ConfigType.STRING);
        createDefaultConfigIfNotExists("system.logo", "/images/logo.png", "系统Logo", "SYSTEM", SystemConfig.ConfigType.STRING);
        
        // 业务配置
        createDefaultConfigIfNotExists("order.auto_confirm_hours", "24", "订单自动确认时间(小时)", "BUSINESS", SystemConfig.ConfigType.INTEGER);
        createDefaultConfigIfNotExists("points.earn_rate", "0.05", "积分获得比例", "BUSINESS", SystemConfig.ConfigType.DECIMAL);
        createDefaultConfigIfNotExists("coupon.expire_days", "30", "优惠券默认有效期(天)", "BUSINESS", SystemConfig.ConfigType.INTEGER);
        
        // 通知配置
        createDefaultConfigIfNotExists("notification.email_enabled", "true", "邮件通知开关", "NOTIFICATION", SystemConfig.ConfigType.BOOLEAN);
        createDefaultConfigIfNotExists("notification.sms_enabled", "false", "短信通知开关", "NOTIFICATION", SystemConfig.ConfigType.BOOLEAN);
        createDefaultConfigIfNotExists("notification.push_enabled", "true", "推送通知开关", "NOTIFICATION", SystemConfig.ConfigType.BOOLEAN);
    }
    
    private void createDefaultConfigIfNotExists(String key, String value, String description, String category, SystemConfig.ConfigType type) {
        if (!existsByKey(key)) {
            SystemConfig config = new SystemConfig();
            config.setConfigKey(key);
            config.setConfigValue(value);
            config.setDescription(description);
            config.setCategory(category);
            config.setType(type);
            config.setIsVisible(true);
            config.setIsEditable(true);
            systemConfigRepository.save(config);
        }
    }
    
    @Override
    public void resetConfigToDefault(String key) {
        // 这里应该实现重置配置到默认值的逻辑
        // 暂时抛出异常提示未实现
        throw new RuntimeException("重置配置功能暂未实现");
    }
    
    @Override
    public boolean existsByKey(String key) {
        return systemConfigRepository.findByConfigKey(key).isPresent();
    }
    
    @Override
    public boolean isValidConfigValue(String key, String value) {
        Optional<SystemConfig> configOpt = systemConfigRepository.findByConfigKey(key);
        if (configOpt.isPresent()) {
            SystemConfig config = configOpt.get();
            try {
                switch (config.getType()) {
                    case INTEGER:
                        Integer.parseInt(value);
                        return true;
                    case DECIMAL:
                        Double.parseDouble(value);
                        return true;
                    case BOOLEAN:
                        Boolean.parseBoolean(value);
                        return true;
                    default:
                        return true;
                }
            } catch (NumberFormatException e) {
                return false;
            }
        }
        return false;
    }
    
    @Override
    public ConfigStatistics getConfigStatistics() {
        Long totalConfigs = systemConfigRepository.count();
        Long visibleConfigs = (long) systemConfigRepository.findByIsVisibleTrueOrderByCategory().size();
        Long editableConfigs = (long) systemConfigRepository.findByIsEditableTrueOrderByCategory().size();
        
        // 统计各分类配置数量
        List<Object[]> categoryStats = systemConfigRepository.countByCategory();
        Long systemConfigs = 0L, businessConfigs = 0L;
        
        for (Object[] stat : categoryStats) {
            String category = (String) stat[0];
            Long count = (Long) stat[1];
            if ("SYSTEM".equals(category)) {
                systemConfigs = count;
            } else if ("BUSINESS".equals(category)) {
                businessConfigs = count;
            }
        }
        
        return new ConfigStatistics(totalConfigs, visibleConfigs, editableConfigs, systemConfigs, businessConfigs);
    }
    
    @Override
    public List<Object[]> getConfigsByCategory() {
        return systemConfigRepository.countByCategory();
    }
    
    @Override
    public List<Object[]> getConfigsByType() {
        return systemConfigRepository.countByType();
    }
}
